/********************************** (C) COPYRIGHT *******************************
 * File Name          : IIC.C
 * Author             : GJ
 * Version            : V2.00
 * Date               : 2018-7-10
 * Description        : Interface of I2C
 *******************************************************************************/
#include "I2c.h"
#include "System.h"
#include "Config.h"

#define IIC_READ (0X01)
#define IIC_WRITE (0X00)
/*100K DELAY5 增加_nop_();到20个*/
/*100K DELAY2 增加_nop_();到10个*/

/*******************************以下为IIC器件操作常用子函数*********************************************************************/
void I2CInit(void)
{
	P1_MOD_OC &= ~(BIT4 + BIT5);
	P1_DIR_PU |= (BIT4 + BIT5);
	P1 |= BIT4 + BIT5;
}

static void I2C_SDA_Out(void)
{
	P1_MOD_OC &= ~BIT5;
	P1_DIR_PU |= BIT5;
}

static void I2C_SDA_In(void)
{
	P1_MOD_OC |= BIT5;
	P1_DIR_PU |= BIT5;
}
/*******************************************************************************
 * Function Name  2 IICStart
 * Description    :
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************************************************************/
void I2CStart(void)
{
	PIN_SDA = 1;
	I2C_SDA_Out();
	PIN_SCL = 1;
	DelayUs(5);
	PIN_SDA = 0; // START:when CLK is high,DATA change form high to low
	DelayUs(2);
	PIN_SCL = 0; // 钳住I2C总线，准备发送或接收数据
}

/*******************************************************************************
 * Function Name  : I2CStop
 * Description    :
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void I2CStop(void)
{
	PIN_SDA = 0;
	I2C_SDA_Out();
	PIN_SCL = 1;
	DelayUs(2);
	PIN_SDA = 1; // 发送I2C总线结束信号
}

/*******************************************************************************
 * Function Name  : Ack_I2c
 * Description    :
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void I2CAck(void)
{
	PIN_SCL = 0;
	I2C_SDA_Out();
	PIN_SDA = 0;
	DelayUs(1);
	PIN_SCL = 1;
	DelayUs(2);
	PIN_SCL = 0;
	I2C_SDA_In();
	PIN_SDA = 1;
}

/*******************************************************************************
 * Function Name  : Nack_I2c
 * Description    :
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void I2CNack(void)
{
	PIN_SCL = 0;
	I2C_SDA_Out();
	PIN_SDA = 1;
	DelayUs(1);
	PIN_SCL = 1;
	DelayUs(2);
	PIN_SCL = 0;
	I2C_SDA_In();
}
/*******************************************************************************
* Function Name  : Ack_I2c
* Description    :等待应答信号到来
					返回值：1，接收应答失败
								0，接收应答成功
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint8_t I2CWaitAck(void)
{
	uint8_t ucErrTime = 0;
	PIN_SDA = 1;
	PIN_SCL = 1;
	I2C_SDA_In();
	DelayUs(2);
	while (PIN_SDA)
	{
		ucErrTime++;
		if (ucErrTime > 250)
		{
			I2CStop();
			return 1;
		}
		DelayUs(1);
	}
	PIN_SCL = 0; // 时钟输出0
	return 0;
}
/*******************************************************************************
 * Function Name  : I2CSendByte
 * Description    :
 * Input          : uint8_t c
 * Output         : None
 * Return         : None
 *******************************************************************************/
void I2CSendByte(uint8_t txd)
{
	uint8_t t;
	PIN_SCL = 0; // 拉低时钟开始数据传输
	I2C_SDA_Out();
	DelayUs(2);
	for (t = 0; t < 8; t++)
	{
		PIN_SDA = (txd & 0x80) >> 7;
		txd <<= 1;
		DelayUs(1);
		PIN_SCL = 1;
		DelayUs(1);
		if (t == 7)
		{
			I2C_SDA_In();
		}
		PIN_SCL = 0;
		DelayUs(1);
	}
}

/*******************************************************************************
 * Function Name  : IICReadByte
 * Description    :
 * Input          : None
 * Output         : None
 * Return         : uint8_t
 *******************************************************************************/
uint8_t I2CReadByte(uint8_t ack)
{
	uint8_t i, receive = 0;
	DelayUs(2);
	I2C_SDA_In();
	for (i = 0; i < 8; i++)
	{
		PIN_SCL = 0;
		DelayUs(2);
		PIN_SCL = 1;
		receive <<= 1;
		if (PIN_SDA)
			receive++;
	}
	if (!ack)
		I2CNack(); // 发送nACK
	else
		I2CAck(); // 发送ACK
	return receive;
}

// int8_t I2CMasterRecv(uint8_t *AOutBuf, uint8_t ASize)
// {
//   int8_t dataCount = 0;
// 	I2CStart();
// 	I2CSendByte(CMD_R_PKT);
// 	I2CWaitAck();
// 	*AOutBuf = dataCount;
//   return dataCount;
// }
